﻿// Self-Hosted WCF Service for Silverlight Template
// Created by Brice Wilson
// http://www.BriceWilson.net

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using System.IO;
using ABMath.ModelFramework.Data;
using GISEntity;
using ABMath.ModelFramework.Transforms;
using ABMath.ModelFramework.Models;

namespace SLServiceLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
    public class GISService : IGISService, IClientAccessPolicy
    {
        //DBServer连接对象
        private Server dbServer = new Server();
        #region IGISService的成员
        //用作预测计算构造的时间序列对象列表
        private List<TimeSeries> TSList = null;
        //作为返回值构造的时间序列对象列表
        private List<MyTimeSeries> resultMyTSList = null;
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }


        public List<MyTimeSeries> GetTimeSeriesList(List<string> names, string tag)
        {
            resultMyTSList = new List<MyTimeSeries>();
            TSList = new List<TimeSeries>();
            //遍历成立列表
            if (names.Count > 0 && (!string.IsNullOrEmpty(tag)))
            {


                foreach (var city in names)
                {
                    using (HnMapEntities databes = new HnMapEntities(dbServer.GetConnectString()))
                    {
                        //时间序列对象中的时间列表
                        List<DateTime> dt = new List<DateTime>();
                        //时间序列对象中的value列表
                        List<Decimal> values = new List<Decimal>();

                        //根据指标tag进行不同的查询
                        if (tag.Equals("GDP"))
                        {
                            //在GDP表中查询对应city的gdp value
                            var queryGDPResult = from gdp in databes.GDPs
                                                 where gdp.CITYNAME.Equals(city)
                                                 select gdp;

                            //构造用以预测计算的时间序列
                            if (queryGDPResult.Count() > 0)
                            {

                                foreach (var gdpitem in queryGDPResult.ToList())
                                {
                                    //按照对应年份和值进行存储
                                    dt.Add(gdpitem.TIME);
                                    values.Add(gdpitem.GDPVALUE);
                                }
                                TSList.Add(TimeSeries.GetTSFromList(city, dt, values, false));
                            }
                        }
                        else if (tag.Equals("人口"))
                        {

                            //在POPULATION表中查询对应city的POPULATION value
                            var queryGDPResult = from population in databes.POPULATIONs
                                                 where population.CITYNAME.Equals(city)
                                                 select population;

                            //构造用以预测计算的时间序列
                            if (queryGDPResult.Count() > 0)
                            {

                                foreach (var gdpitem in queryGDPResult.ToList())
                                {
                                    //按照对应年份和值进行存储
                                    dt.Add(gdpitem.TIME);
                                    values.Add(gdpitem.POPVALUE);
                                }
                                TSList.Add(TimeSeries.GetTSFromList(city, dt, values, false));
                            }
                        }

                    }

                }
                //对预测时间序列列表中的每个时间序列进行预测计算
                //遍历时间序列列表
                foreach (var ts in TSList)
                {
                    //对时间序列进行LogReturn变换
                    LogReturnTransformation lrTransform = new LogReturnTransformation();
                    StringBuilder strBulider = new StringBuilder();
                    lrTransform.SetInput(0, ts, strBulider);
                    TimeSeries transformedTS = new TimeSeries();
                    lrTransform.Recompute();
                    transformedTS = lrTransform.GetOutput(0) as TimeSeries;
                    //进行模型预测
                    ARMAModel model = new ARMAModel(2, 2);
                    model.SetInput(0, transformedTS, strBulider);
                    TimeSeries modelTS = new TimeSeries();
                    model.FitByMLE(250, 250, 0, null);
                    //进行预测
                    var forecaster = new ForecastTransform();

                    var futureTimes = new List<DateTime>();
                    var nextTime = transformedTS.GetLastTime();
                    for (int t = 0; t < 3; ++t)                    // go eight days into the future beyond the end of the data we have
                    {
                        nextTime = nextTime.AddYears(1);
                        futureTimes.Add(nextTime);
                    }
                    forecaster.FutureTimes = futureTimes.ToArray(); // these are future times at which we want forecasts
                    // for now, ARMA models do not use the times in any meaningful way when forecasting,
                    // they just assume that these are the timestamps for the next sequential points
                    // after the end of the existing time series

                    forecaster.SetInput(0, model, null);            // the ARMA model used for forecasting
                    forecaster.SetInput(1, transformedTS, null);    // the original data

                    // normally you would call the Recompute() method of a transform, but there is no need
                    // here; it is automatically called as soon as all inputs are set to valid values (in the 2 statements above)
                    var predictors = forecaster.GetOutput(0) as TimeSeries;
                    //遍历预测结果，进行LogReturn的逆变换，求解真实的预测结果
                    for (int i = 0; i < predictors.Count; i++)
                    {
                        if (i == 0)
                        {
                            var value = predictors.ValueAtTime(predictors.TimeStamp(i));
                            var lastValue = ts.ValueAtTime(ts.GetLastTime());
                            predictors.SetValue(i, getTrueValue(value, lastValue));
                        }
                        else
                        {
                            var value = predictors.ValueAtTime(predictors.TimeStamp(i));
                            var lastValue = predictors.ValueAtTime(predictors.TimeStamp(i - 1));
                            predictors.SetValue(i, getTrueValue(value, lastValue));
                        }

                    }
                    // now predictors is a time series of the forecast values for the next 8 days
                    // that is, predictors[0] is the predictive mean of X_{101} given X_1,...,X_100,
                    //          predictors[1] is the predictive mean of X_{102} given X_1,...,X_100, etc.
                    //把预测结果追加到现有时间序列末尾
                    ts.Add(predictors, false);
                }
                //构造用以返回的时间序列
                foreach (var item in TSList)
                {
                    //Console.WriteLine(item.Title);
                    MyTimeSeries tempMyTS = new MyTimeSeries();
                    tempMyTS.Titel = item.Title;
                    for (int i = 0; i < item.Count; i++)
                    {
                        // Console.WriteLine("{0} in {1} is: {2}", item.Title, item.TimeStamp(i), item.ValueAtTime(item.TimeStamp(i)));
                        tempMyTS.Times.Add(item.TimeStamp(i));
                        tempMyTS.Values.Add(Convert.ToDecimal(item.ValueAtTime(item.TimeStamp(i))));
                    }
                    resultMyTSList.Add(tempMyTS);

                }
            }
            return resultMyTSList;
        }

        //产业集群
        public decimal GetLQ(string cityName, string countyName, DateTime Time, string industryTypeName, string industryType)
        {
            decimal lqvalue = 0;//返回所求区位商的数值
            IndustrySignleValue isv = new IndustrySignleValue();//求所选产业在所选地区的产值
            Console.WriteLine("isv" + isv);
            SignleAreaValue sav = new SignleAreaValue();//所选地区的所有产业的产值求和
            Console.WriteLine("sav" + sav);
            WholeIndustryValue wiv = new WholeIndustryValue();//所选产业在所有地区的产值求和
            Console.WriteLine("wiv" + wiv);
            WholeAreaValue wav = new WholeAreaValue();//所有地区的所有产业的产值求和
            Console.WriteLine("wav" + wav);
            lqvalue = (isv.GetIndustrySignleValue(cityName, countyName, Time, industryTypeName, industryType) / sav.GetSignleAreaValue(Time, cityName, industryTypeName, countyName)) / (wiv.GetWholeIndustryValue(Time, industryType, industryTypeName) / wav.GetWholeAreaValue(Time, industryTypeName));
            return lqvalue;

        }
        public Center GetCenter(string name, string type, List<Country> countryList)
        {
            Center center = new Center { Name = name, Type = type };
            List<decimal> totalDiList = new List<decimal>();
            List<decimal> totalXDiList = new List<decimal>();
            List<decimal> totalYDiList = new List<decimal>();
            if (countryList.Count > 0 && !string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(type))
            {


                //判断是省还是地市
                if (name.Equals("湖南省"))
                {
                    //先构造一个地市的列别出来
                    List<City> cityList = new List<City>();
                    if (type.Equals("GDP"))
                    {
                        using (HnMapEntities database = new HnMapEntities(this.dbServer.GetConnectString()))
                        {
                            var queryCity = from city in database.CITies
                                            select city;
                            foreach (var item in queryCity.ToList<CITY>())
                            {
                                City tempCity =new City { CityName = item.NAME.ToString()};

                                Center tempCenter = GetCenter(item.NAME, type, countryList);

                                foreach (var year in tempCenter.Times)
                                {
                                    tempCity.TimeList.Add(year);

                                    tempCity.PointList.Add(tempCenter.PointList[tempCenter.Times.IndexOf(year)]);

                                    var queryCityGDP = from cityGDP in database.GDPs
                                                       where cityGDP.TIME.Equals(year) && cityGDP.CITYNAME.Equals(item.NAME)
                                                       select cityGDP.GDPVALUE;

                                    tempCity.ValueList.Add(queryCityGDP.First());
                                }
                                cityList.Add(tempCity);
                            }
                            //计算湖南省的GDP
                            List<decimal> parentValueList = new List<decimal>();
                            for (int i = 0; i < cityList[0].TimeList.Count; i++)
                            {
                                decimal tempParentValue = 0;
                                foreach (var city in cityList)
                                {
                                    tempParentValue += city.ValueList[i];
                                }
                                parentValueList.Add(tempParentValue);
                            }
                            //
                            foreach (var city in cityList)
                            {
                                bool IsFirstLoop = true;
                                foreach (var year in city.TimeList)
                                {
                                    if (IsFirstLoop)
                                    {
                                        center.Times.Add(year);
                                    }
                                    city.ParentValueList.Add(parentValueList[city.TimeList.IndexOf(year)]);
                                }
                                city.countDi();
                                city.counXYDi();
                                IsFirstLoop = false;
                            }
                            //
                            foreach (var year in center.Times)
                            {
                                decimal tempTotalDi = 0;
                                decimal tempTotalXDi = 0;
                                decimal tempTotalYDi = 0;
                                foreach (var city in cityList)
                                {
                                    tempTotalDi += city.GetDiByTime(year);

                                    tempTotalXDi += city.GetXDiByTime(year);

                                    tempTotalYDi += city.GetYDiByTime(year);
                                }
                                totalDiList.Add(tempTotalDi);

                                totalXDiList.Add(tempTotalXDi);

                                totalYDiList.Add(tempTotalYDi);
                            }
                            foreach (var year in center.Times)
                            {
                                try
                                {
                                    int tempIndex = center.Times.IndexOf(year);

                                    decimal tempX = totalXDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    decimal tempY = totalYDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    center.PointList.Add(new Point { X = tempX.ToString(), Y = tempY.ToString() });
                                }
                                catch (Exception)
                                {

                                    throw;
                                }
                            }

                        }
                    }
                }
                else
                {
                    //计算某个地市的某种经济指标的重心
                    if (type.Equals("GDP"))
                    {

                        //从数据库得到长沙的区县列表,并且从传入的地区列表中清除不是该地市的区县
                        List<Country> tempCountryList = new List<Country>();
                        //List<Country> tempCountryList = new List<Country>();
                        using (HnMapEntities database = new HnMapEntities(this.dbServer.GetConnectString()))
                        {
                            var queryCountryName = from countryName in database.COUNTYGDPs
                                                   where countryName.CITYNAME.Equals(name)
                                                   select countryName.COUNTYNAME;
                            //bool IsFirstLoop = true;
                            foreach (var tempName in queryCountryName.ToList().Distinct())
                            {
                                foreach (var country in countryList)
                                {
                                    if (country.CountryName.Equals(tempName))
                                    {
                                        //给参数区县列表中的这个区县的地市属性赋值,省的属性里面有个对应年份的Value
                                        var queryCity = from city in database.GDPs
                                                        where city.CITYNAME.Equals(name)
                                                        orderby city.TIME
                                                        select city;
                                        country.ParentCity = new City { CityName = name };

                                        foreach (var item in queryCity.ToList())
                                        {
                                            country.ParentCity.TimeList.Add(item.TIME);

                                            country.ParentCity.ValueList.Add(item.GDPVALUE);
                                            //if (IsFirstLoop)
                                            //{
                                            //    center.Times.Add(item.TIME);
                                            //}
                                        }
                                        Country tempCountry = new Country();
                                        tempCountry = country.clone();
                                        tempCountryList.Add(tempCountry);
                                    }
                                    //IsFirstLoop = false;
                                }
                            }
                            //遍历属于该地市name的区县的列表，进行数据库查询赋值操作
                            bool IsFirstLoop = true;
                            foreach (var country in tempCountryList)
                            {
                                var queryCountry = from countryDB in database.COUNTYGDPs
                                                   where countryDB.COUNTYNAME.Equals(country.CountryName)
                                                   orderby countryDB.TIME
                                                   select countryDB;
                                //country.TimeList = new List<DateTime>();
                                //country.ValueList = new List<decimal>();
                                foreach (var item in queryCountry.ToList())
                                {
                                    //country.TimeList = new List<DateTime>();
                                    country.TimeList.Add(item.TIME);

                                    country.ValueList.Add(item.GDPVALUE);

                                    if (IsFirstLoop)
                                    {
                                        center.Times.Add(item.TIME);
                                    }
                                }
                                IsFirstLoop = false;
                                //计算该区县的Di
                                country.countDi();
                                //计算该区县的XYDI
                                country.counXYDi();
                                //decimal tempTotalDi = 0;
                                //decimal tempTotalXDi = 0;
                                //decimal tempTotalYDi = 0;
                                //foreach (var year in country.TimeList)
                                //{
                                //    tempTotalDi += country.GetDiByTime(year);

                                //    tempTotalXDi += country.GetXDiByTime(year);

                                //    tempTotalYDi += country.GetYDiByTime(year);
                                //}

                                //totalDiList.Add(tempTotalDi);

                                //totalXDiList.Add(tempTotalXDi);

                                //totalYDiList.Add(tempTotalYDi);
                            }
                            foreach (var year in center.Times)
                            {
                                decimal tempTotalDi = 0;
                                decimal tempTotalXDi = 0;
                                decimal tempTotalYDi = 0;
                                foreach (var country in tempCountryList)
                                {
                                    tempTotalDi += country.GetDiByTime(year);

                                    tempTotalXDi += country.GetXDiByTime(year);

                                    tempTotalYDi += country.GetYDiByTime(year);
                                }
                                totalDiList.Add(tempTotalDi);

                                totalXDiList.Add(tempTotalXDi);

                                totalYDiList.Add(tempTotalYDi);
                            }
                            //给返回结果赋值
                            //center.Times.Distinct();
                            foreach (var year in center.Times)
                            {
                                try
                                {
                                    int tempIndex = center.Times.IndexOf(year);

                                    decimal tempX = totalXDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    decimal tempY = totalYDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    center.PointList.Add(new Point { X = tempX.ToString(), Y = tempY.ToString() });
                                }
                                catch (Exception)
                                {

                                    throw;
                                }
                            }
                        }

                    }
                    else if (type.Equals("人口"))
                    {
                        //从数据库得到长沙的区县列表,并且从传入的地区列表中清除不是该地市的区县
                        List<Country> tempCountryList = new List<Country>();
                        //List<Country> tempCountryList = new List<Country>();
                        using (HnMapEntities database = new HnMapEntities(this.dbServer.GetConnectString()))
                        {
                            var queryCountryName = from countryName in database.COUNTYPOPULATIONs
                                                   where countryName.CITYNAME.Equals(name)
                                                   select countryName.COUNTYNAME;
                            //bool IsFirstLoop = true;
                            foreach (var tempName in queryCountryName.ToList().Distinct())
                            {
                                foreach (var country in countryList)
                                {
                                    if (country.CountryName.Equals(tempName))
                                    {
                                        //给参数区县列表中的这个区县的地市属性赋值,省的属性里面有个对应年份的Value
                                        var queryCity = from city in database.POPULATIONs
                                                        where city.CITYNAME.Equals(name)
                                                        orderby city.TIME
                                                        select city;
                                        country.ParentCity = new City { CityName = name };

                                        foreach (var item in queryCity.ToList())
                                        {
                                            country.ParentCity.TimeList.Add(item.TIME);

                                            country.ParentCity.ValueList.Add(item.POPVALUE);
                                            //if (IsFirstLoop)
                                            //{
                                            //    center.Times.Add(item.TIME);
                                            //}
                                        }
                                        Country tempCountry = new Country();
                                        tempCountry = country.clone();
                                        tempCountryList.Add(tempCountry);
                                    }
                                    //IsFirstLoop = false;
                                }
                            }
                            //遍历属于该地市name的区县的列表，进行数据库查询赋值操作
                            bool IsFirstLoop = true;
                            foreach (var country in tempCountryList)
                            {
                                var queryCountry = from countryDB in database.COUNTYPOPULATIONs
                                                   where countryDB.COUNTYNAME.Equals(country.CountryName)
                                                   orderby countryDB.TIME
                                                   select countryDB;
                                //country.TimeList = new List<DateTime>();
                                //country.ValueList = new List<decimal>();
                                foreach (var item in queryCountry.ToList())
                                {
                                    //country.TimeList = new List<DateTime>();
                                    country.TimeList.Add(item.TIME);

                                    country.ValueList.Add(item.POPVALUE);

                                    if (IsFirstLoop)
                                    {
                                        center.Times.Add(item.TIME);
                                    }
                                }
                                IsFirstLoop = false;
                                //计算该区县的Di
                                country.countDi();
                                //计算该区县的XYDI
                                country.counXYDi();
                                //decimal tempTotalDi = 0;
                                //decimal tempTotalXDi = 0;
                                //decimal tempTotalYDi = 0;
                                //foreach (var year in country.TimeList)
                                //{
                                //    tempTotalDi += country.GetDiByTime(year);

                                //    tempTotalXDi += country.GetXDiByTime(year);

                                //    tempTotalYDi += country.GetYDiByTime(year);
                                //}

                                //totalDiList.Add(tempTotalDi);

                                //totalXDiList.Add(tempTotalXDi);

                                //totalYDiList.Add(tempTotalYDi);
                            }
                            foreach (var year in center.Times)
                            {
                                decimal tempTotalDi = 0;
                                decimal tempTotalXDi = 0;
                                decimal tempTotalYDi = 0;
                                foreach (var country in tempCountryList)
                                {
                                    tempTotalDi += country.GetDiByTime(year);

                                    tempTotalXDi += country.GetXDiByTime(year);

                                    tempTotalYDi += country.GetYDiByTime(year);
                                }
                                totalDiList.Add(tempTotalDi);

                                totalXDiList.Add(tempTotalXDi);

                                totalYDiList.Add(tempTotalYDi);
                            }
                            //给返回结果赋值
                            //center.Times.Distinct();
                            foreach (var year in center.Times)
                            {
                                try
                                {
                                    int tempIndex = center.Times.IndexOf(year);

                                    decimal tempX = totalXDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    decimal tempY = totalYDiList.ElementAt(tempIndex) / totalDiList.ElementAt(tempIndex);

                                    center.PointList.Add(new Point { X = tempX.ToString(), Y = tempY.ToString() });
                                }
                                catch (Exception)
                                {

                                    throw;
                                }
                            }
                        }
                    }
                }
            }
            return center;
        }
        #endregion

        #region IClientAccessPolicy Members

        System.IO.Stream IClientAccessPolicy.GetCrossDomainPolicy()
        {
            // TODO: Modify the string below to set the desired cross-domain policy
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"">
<cross-domain-policy>
  <allow-access-from domain=""*"" />
</cross-domain-policy>";
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }
        System.IO.Stream IClientAccessPolicy.GetClientAccessPolicy()
        {
            // TODO: Modify the string below to set the desired cross-domain policy
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
    <cross-domain-access>
        <policy>
            <allow-from http-request-headers=""*"">
                <domain uri=""*""/>
            </allow-from>
            <grant-to>
                <resource path=""/"" include-subpaths=""true""/>
            </grant-to>
        </policy>
    </cross-domain-access>
</access-policy>";
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }

        #endregion

        /// <summary>
        /// 进行logReturn的逆变换获得预测值的真实值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private double getTrueValue(double value, double lastValue)
        {
            double trueValue = 0;

            var logValue = Math.Log(lastValue) + value;

            trueValue = Math.Exp(logValue);

            return trueValue;
        }
    }
}
